package com.ifacebox.arcsoft.face;

import com.arcsoft.face.*;
import com.arcsoft.face.enums.CompareModel;
import com.arcsoft.face.enums.ErrorInfo;
import com.arcsoft.face.toolkit.ImageInfo;
import com.ifacebox.arcsoft.face.model.FacePosition;
import org.apache.commons.pool2.ObjectPool;

import java.util.ArrayList;
import java.util.List;

/**
 * @author znn
 */
public class ArcSoftFaceEngine extends FaceEngine implements AutoCloseable {
    private final ObjectPool<ArcSoftFaceEngine> objectPool;

    public ArcSoftFaceEngine(String libPath, ObjectPool<ArcSoftFaceEngine> objectPool) {
        super(libPath);
        this.objectPool = objectPool;
    }

    public ActiveFileInfo create(String appId, String sdkKey, EngineConfiguration engineConfiguration) throws Exception {
        int mok = super.activeOnline(appId, sdkKey);
        if (ErrorInfo.MOK.getValue() != mok && ErrorInfo.MERR_ASF_ALREADY_ACTIVATED.getValue() != mok) {
            throw new Exception(String.format("激活人脸引擎失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        mok = super.init(engineConfiguration);
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("初始化人脸引擎失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        ActiveFileInfo activeFileInfo = new ActiveFileInfo();
        mok = super.getActiveFileInfo(activeFileInfo);
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("获取激活文件信息失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        return activeFileInfo;
    }

    public void destroy() throws Exception {
        int mok = super.unInit();
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("销毁人脸引擎擎失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
    }

    public FacePosition facePosition(Rect faceRect) {
        FacePosition facePosition = new FacePosition();
        facePosition.setX(faceRect.left);
        facePosition.setY(faceRect.top);
        facePosition.setWidth(faceRect.right - faceRect.left);
        facePosition.setHeight(faceRect.bottom - faceRect.top);
        return facePosition;
    }

    public List<FaceInfo> faceDetection(ImageInfo imageInfo) throws Exception {
        List<FaceInfo> faceInfoList = new ArrayList<>();
        int mok = super.detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("人脸检测失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        return faceInfoList;
    }

    public FaceFeature faceFeature(ImageInfo imageInfo, FaceInfo faceInfo) throws Exception {
        FaceFeature faceFeature = new FaceFeature();
        int mok = super.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfo, faceFeature);
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("人脸特征提取失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        return faceFeature;
    }

    public float faceCompare(FaceFeature faceFeature1, FaceFeature faceFeature2) throws Exception {
        FaceSimilar faceSimilar = new FaceSimilar();
        int mok = super.compareFaceFeature(faceFeature1, faceFeature2, CompareModel.ID_PHOTO, faceSimilar);
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("人脸特征比对失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        return faceSimilar.getScore();
    }

    public Boolean faceLiveness(ImageInfo imageInfo, List<FaceInfo> faceInfoList, float rgbThreshold, float irThreshold) throws Exception {
        int mok = super.process(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList, FunctionConfiguration.builder().supportLiveness(true).build());
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("人脸属性检测失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        mok = super.setLivenessParam(rgbThreshold, irThreshold);
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("设置活体阈值失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        List<LivenessInfo> livenessInfoList = new ArrayList<>();
        mok = super.getLiveness(livenessInfoList);
        if (ErrorInfo.MOK.getValue() != mok) {
            throw new Exception(String.format("人脸活体检测失败！(%d:%s)", mok, ErrorInfo.getValidEnum(mok).toString()));
        }
        for (LivenessInfo livenessInfo : livenessInfoList) {
            if (livenessInfo.getLiveness() == 1) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void close() throws Exception {
        if (objectPool != null) {
            objectPool.returnObject(this);
        }
    }
}
